package com.sgzn.sgpay.util;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;

/**
 * Created by dmd on 2014/5/14.
 */
@Slf4j
public class InjectInstanceUtil {
    public static void injectProperties(Map parameterMaps, Object target, String prefix) {
        injectProperties(parameterMaps, target, prefix, null);
    }

    public static void injectProperties(Map parameterMaps, Object target, String prefix, Set<String> ignoreFields) {
        Class<?> paramType = target.getClass();
        for (Method mtd : paramType.getMethods()) {
            if (Modifier.isPublic(mtd.getModifiers()) && mtd.getName().startsWith("set")
                    && mtd.getParameterTypes().length == 1) {
                //目标类字段名
                String p = mtd.getName().substring(3, 4).toLowerCase() + mtd.getName().substring(4);
                if (ignoreFields != null && ignoreFields.contains(p)) {
                    //如果字段名与注解包含的忽略字段同名，不处理
                    continue;
                }
                Class<?> type = mtd.getParameterTypes()[0];
                boolean primitive = ClassUtils.isPrimitive(type);
                Object v = null;
                if (prefix != null) {
                    v = parameterMaps.get(prefix + "." + p);
                }
                if (v == null) {
                    v = parameterMaps.get(p);
                }
                if (v == null && !primitive) {
                    try {
                        int prefixLength;
                        v = ClassUtils.createInstance(type);
                        if (v == null) {
                            log.warn("create {} instance happen error,the value is null!", type.getSimpleName());
                            continue;
                        }
                        if (prefix != null) {
                            prefixLength = prefix.length() + 1;
                            prefix = prefix + "." + p;
                        } else {
                            prefixLength = p.length();
                            prefix = p;
                        }
                        //不支持递归的复杂子字段
                        injectProperties(parameterMaps, v, prefix, null);
                        if (prefix.length() == prefixLength) {
                            prefix = null;
                        } else {
                            prefix = prefix.substring(prefixLength - 1);
                        }
                    } catch (Exception e) {
                        log.warn("create {} instance happen error" + e.getMessage(), type.getSimpleName(), e);
                    }
                }
                if (v != null) {
                    try {
                        mtd.invoke(target, new Object[]{CompatibleTypeUtils.compatibleTypeConvert(v, mtd.getParameterTypes()[0])});
                    } catch (Exception e) {
                        log.warn(e.getMessage(), e);
                    }
                }
            }
        }
    }
}
